package ch.subgate.pongwars;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;

/**
 * @author Samuel Aeberhard
 * This class was created in order to centralize resources used for drawing. GameObjects will still
 * have their own draw() methods.
 */
public class Renderer {

    private Bitmap battlefield;

    private Paint paint;

    public Renderer(Context context) {
        // Instantiate and prepare render objects
        paint = new Paint();
        Typeface face = Typeface.createFromAsset(
                context.getAssets(),
                "fonts/ca.ttf");
        paint.setTypeface(face);
    } // Constructor

    /**
     * Initialize renderer. Predraws the battlefield onto a bitmap, which is then used to draw
     * the battlefield with one call. Needs to be called before any draw() calls.
     * @param gameContext The initialized GameContext containing the necessary metrics
     */
    public void init(GameContext gameContext) {
        if (battlefield != null) { battlefield.recycle(); } // recycle when screen changes
        battlefield = Bitmap.createBitmap(
                (int)gameContext.battlefieldWidth,
                (int)gameContext.battlefieldHeight,
                Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(battlefield);

        // draw white battlefield background
        c.drawColor(Color.WHITE);

        // draw field areas
        paint.setColor(0xffeeeeee);
        c.drawCircle(
                gameContext.battlefieldWidth / 2.0f,
                gameContext.battlefieldHeight / 2.0f,
                (0.1f * gameContext.battlefieldWidth), paint);
        c.drawCircle(
                gameContext.battlefieldWidth / 2.0f,
                0.0f,
                (0.25f * gameContext.battlefieldWidth), paint);
        c.drawCircle(
                gameContext.battlefieldWidth / 2.0f,
                gameContext.battlefieldHeight,
                (0.25f * gameContext.battlefieldWidth), paint);

        // draw field lines
        paint.setStrokeWidth(1.0f);
        paint.setColor(Constants.RENDER_LINE_COLOR);
        c.drawLine(
                0.0f, gameContext.battlefieldHeight / 2.0f,
                gameContext.battlefieldWidth, gameContext.battlefieldHeight / 2.0f, paint);
        c.drawLine(
                0.0f, 0.25f * gameContext.battlefieldHeight,
                gameContext.battlefieldWidth, 0.25f * gameContext.battlefieldHeight, paint);
        c.drawLine(
                0.0f, 0.75f * gameContext.battlefieldHeight,
                gameContext.battlefieldWidth, 0.75f * gameContext.battlefieldHeight, paint);
    } // init

    /**
     * Main drawing method of the renderer
     * @param canvas The canvas used for drawing
     * @param gameContext The GameContext containing the current game state
     */
    public void draw(Canvas canvas, GameContext gameContext) {
        // Draw battlefield
        drawBattlefield(canvas, gameContext);

        // Draw players
        gameContext.playerRed.draw(canvas, gameContext);
        gameContext.playerBlue.draw(canvas, gameContext);

        // Draw ball
        gameContext.ball.draw(canvas, gameContext);

        // Draw UI
        paint.setTextSize(1.5f * gameContext.unitWidth);
        paint.setColor(Color.WHITE);
        paint.setTextAlign(Paint.Align.RIGHT);
        int mb = gameContext.checkMatchBall();
        if (mb < 0) { paint.setColor(Color.RED); } else { paint.setColor(Color.BLACK); }
        canvas.drawText(
                Integer.toString(gameContext.playerRed.mPoints),
                gameContext.battlefieldLeft + (3.0f * gameContext.unitWidth),
                (gameContext.surfaceHeight / 2.0f) - (0.5f * gameContext.unitWidth),
                paint);
        if (mb > 0) { paint.setColor(Color.RED); } else { paint.setColor(Color.BLACK); }
        canvas.drawText(
                Integer.toString(gameContext.playerBlue.mPoints),
                gameContext.battlefieldLeft + (3.0f * gameContext.unitWidth),
                (gameContext.surfaceHeight / 2.0f) + (1.5f * gameContext.unitWidth),
                paint);
        if (!gameContext.getGameIsRunning() || gameContext.timeOut > 0) {
            drawMessage(canvas, gameContext);
        }
    } // draw

    /**
     * Draws the battlefield onto a canvas
     * @param canvas The canvas on which the battlefield is drawn
     * @param gameContext Initialized GameContext with the necessary metrics
     */
    public void drawBattlefield(Canvas canvas, GameContext gameContext) {
        // draw a black background
        canvas.drawColor(Color.BLACK);

        // draw battlefield
        canvas.drawBitmap(battlefield, gameContext.battlefieldLeft, gameContext.battlefieldTop, null);
    } // drawBattlefield

    /**
     * Draws a message in a rectangle on the screen
     * @param canvas The canvas on which the message is drawn
     * @param gameContext The GameContext object containing the metrics and message to draw
     */
    public void drawMessage(Canvas canvas, GameContext gameContext) {
        // draw the rectangle
        paint.setColor(0x33cccccc);
        canvas.drawRect(
                gameContext.battlefieldLeft + (Constants.MESSAGE_LEFT * gameContext.unitWidth),
                gameContext.battlefieldTop + (Constants.MESSAGE_TOP * gameContext.unitWidth),
                gameContext.battlefieldLeft + (Constants.MESSAGE_RIGHT * gameContext.unitWidth),
                gameContext.battlefieldTop + (Constants.MESSAGE_BOTTOM * gameContext.unitWidth),
                paint);
        // draw the message
        paint.setColor(Color.BLACK);
        paint.setTextSize(1.5f * gameContext.unitWidth);
        paint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText(
                gameContext.mMsg,
                gameContext.surfaceWidth / 2.0f,
                gameContext.surfaceHeight / 2.0f,
                paint);
        if (gameContext.getGameIsRunning()) { // no need to display the timeout if its not counting
            canvas.drawText(
                    ((int)(gameContext.timeOut * 10) / 10.0f) + " s",
                    gameContext.surfaceWidth / 2.0f,
                    (gameContext.surfaceHeight / 2.0f) + (2.0f * gameContext.unitWidth),
                    paint);
        } else {
            canvas.drawText(
                    Constants.REPLAY_TEXT,
                    gameContext.surfaceWidth / 2.0f,
                    (gameContext.surfaceHeight / 2.0f) + (2.0f * gameContext.unitWidth),
                    paint);
            if (gameContext instanceof GameContextP2P) {
                paint.setTextSize(0.8f * gameContext.unitWidth);
                if (((GameContextP2P) gameContext).mIsReady) {
                    paint.setColor(Color.GREEN);
                    canvas.drawText(
                            "YOU: READY",
                            gameContext.surfaceWidth / 2.0f,
                            (gameContext.surfaceHeight / 2.0f) + (2.8f * gameContext.unitWidth),
                            paint);
                } else {
                    paint.setColor(Color.RED);
                    canvas.drawText(
                            "YOU: UNREADY",
                            gameContext.surfaceWidth / 2.0f,
                            (gameContext.surfaceHeight / 2.0f) + (2.8f * gameContext.unitWidth),
                            paint);
                }
                if (((GameContextP2P) gameContext).mOpponentIsReady) {
                    paint.setColor(Color.GREEN);
                    canvas.drawText(
                            "OPPONENT: READY",
                            gameContext.surfaceWidth / 2.0f,
                            (gameContext.surfaceHeight / 2.0f) + (3.5f * gameContext.unitWidth),
                            paint);
                } else {
                    paint.setColor(Color.RED);
                    canvas.drawText(
                            "OPPONENT: UNREADY",
                            gameContext.surfaceWidth / 2.0f,
                            (gameContext.surfaceHeight / 2.0f) + (3.5f * gameContext.unitWidth),
                            paint);
                }
            }
        } // if
    } // drawMessage

} // Renderer
